#include "sessionfriendarea.h"

#include <QScrollBar>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QStyleOption>
#include <QPainter>
#include <QMouseEvent>

#include "model/data.h"
#include "mainwidget.h"
#include "model/datacenter.h"
#include "debug.h"

using namespace model;

SessionFriendArea::SessionFriendArea(QWidget *parent)
    : QScrollArea{parent}
{
    //1. 设置基础属性
    this->setWidgetResizable(true);

    //2. 设置滚动条宽度
    this->verticalScrollBar()->setStyleSheet( "QScrollBar:vertical {"
                                             "    background: transparent;"
                                             "    width: 2px;"
                                             "    border-radius: 4px;"         // 设置边框圆角
                                             "}"
                                             "QScrollBar::handle:vertical {"
                                             "    background: rgba(0, 0, 0, 50%);"
                                             "    border-radius: 5px;"
                                             "    min-height: 20px;"
                                             "}"
                                             "QScrollBar::add-line, QScrollBar::sub-line {"
                                             "    background: none;"
                                             "    border: none;"
                                             "}"
                                             "QScrollBar::add-page, QScrollBar::sub-page {"
                                             "    background: none;"
                                             "}");
    //隐藏水平滚动条
    this->horizontalScrollBar()->setStyleSheet("QScrollBar:horizontal {height: 0px;}");
    //将边框移除
    this->setStyleSheet("QWidget: {border: none;}");

    //3. 将widget创建出来
    container = new QWidget();
    container->setFixedWidth(310);
    this->setWidget(container);

    //4. 创建布局
    QVBoxLayout* layout = new QVBoxLayout();
    layout->setContentsMargins(0,0,0,0);
    layout->setSpacing(0);
    layout->setAlignment(Qt::AlignTop);
    container->setLayout(layout);

// // for test
// for(int i =0; i<500; i++){
//     QPushButton* btn = new QPushButton("这是测试消息");
//     layout->addWidget(btn);
// }

#if TEST_UI
    QIcon icon(":/resource/image/avatarDefault.png");
    for(int i =0; i<30; i++){
        this->addItem(SessionItemType,QString::number(i),icon,"张三" + QString::number(i),"最后一条消息" + QString::number(i));
    }
#endif
}

void SessionFriendArea::clear()
{
    QLayout* layout = container->layout();
    for(int i = layout->count() -1; i >=0 ; i--){
        QLayoutItem* item = layout->takeAt(i);
        // 上面只是将内容清除了，要释放空间
        if(item->widget()){
            delete item->widget();
        }
    }
}

void SessionFriendArea::addItem(ItemType itemType,const QString& id,const QIcon& avatar,const QString& name,const QString& text)
{
    if (container == nullptr || container->layout() == nullptr) {
        LOG() << "错误: container 或 layout 为空!";
        return;
    }
    SessionFriendItem* item = nullptr;
    if (itemType == SessionItemType) {
        item = new SessionItem(this, id, avatar, name, text);
    } else if (itemType == FriendItemType) {
        item = new FriendItem(this, id, avatar, name, text);
    } else if (itemType == ApplyItemType) {
        item = new ApplyItem(this, id, avatar, name);
    } else {
        LOG() << "错误的 ItemType! itemType=" << itemType;
        return;
    }
    container->layout()->addWidget(item);
}

SessionFriendItem::SessionFriendItem(QWidget* owner,const QIcon& avatar,const QString& name,const QString& text)
    :owner(owner)
{
    //设置该 QWidget 的背景颜色为浅灰色。
    this->setStyleSheet("QWidget {background-color: rgb(231,231,231)}");
    this->setFixedHeight(70); // 不是setFixedWidth

    QGridLayout* layout = new QGridLayout();
    layout->setContentsMargins(10,0,0,0);
    layout->setHorizontalSpacing(5);
    layout->setVerticalSpacing(0);
    this->setLayout(layout);

    //创建头像
    QPushButton* avatarBtn = new QPushButton();
    avatarBtn->setFixedSize(50,50);
    avatarBtn->setIcon(avatar);
    avatarBtn->setIconSize(QSize(50,50));
    avatarBtn->setStyleSheet("QPushButton {border: none;}");
    avatarBtn->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);

    //创建名字
    QLabel* nameLabel = new QLabel();
    nameLabel->setText(name);
    nameLabel->setFixedHeight(35);
    nameLabel->setStyleSheet("QLabel { font-size: 18px; font-weight: 600; }");
    //调整文字对齐方式,为了样式好看
    nameLabel->setAlignment(Qt::AlignBottom);
    nameLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);

    //创建消息预览 QLabel
    messageLabel = new QLabel();
    messageLabel->setText(text);
    messageLabel->setFixedHeight(35);
    messageLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);

    // 创建分隔线
    QWidget* separatorLine = new QWidget();
    separatorLine->setFixedHeight(1);
    separatorLine->setStyleSheet("background-color: rgb(255,255,255);");

    // 将头像添加到布局中
    layout->addWidget(avatarBtn, 0, 0, 2, 2);
     // 将名字添加到布局中
    layout->addWidget(nameLabel, 0, 2, 1, 6);
     // 将消息添加到布局中
    layout->addWidget(messageLabel, 1, 2, 1, 6);
     // 将分割线添加到布局中
    layout->addWidget(separatorLine, 2, 2, 1, 6);
}

//官网文档中给出的要求，如果一个子类继承自widget,那么要将背景颜色生效，需要重写paintEvent
void SessionFriendItem::paintEvent(QPaintEvent* event)
{
    (void) event;
    QStyleOption opt;
    opt.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

void SessionFriendItem::mousePressEvent(QMouseEvent* event)
{
    (void)event;

    select(event);
}

void SessionFriendItem::select(QMouseEvent* event)
{
    //清空其余元素的样式
    //this->parentWidget() 返回当前控件的父控件指针（QWidget* 类型）。
    //children() 是 QObject 类的一个成员函数（QWidget 继承自 QObject）
    //children() 返回一个 QObjectList，这是一个包含父控件所有子对象（QObject 的指针）的列表。
    const QObjectList& children = this->parentWidget()->children();
    for(auto child : children){
        if(!child->isWidgetType()){
            //如果不是QWidget类型 直接跳过 判断下一个
            continue;
        }
        SessionFriendItem* widget = dynamic_cast<SessionFriendItem*>(child);
        widget->selected = false;

        widget->setStyleSheet("QWidget {background-color: rgb(231,231,231)}");
    }

    if(event->button() == Qt::LeftButton){
        this->setStyleSheet("QWidget {background-color: rgb(205,205,205)}");
        this->selected = true;
    }

    this->active();
}

//鼠标还没有点击，只是在哪个QWidget中，将颜色变深
void SessionFriendItem::enterEvent(QEnterEvent* event)
{
    (void)event;
    if (this->selected) {
        return;
    }
    // 设置一个更深的颜色
    this->setStyleSheet("QWidget { background-color: rgb(215, 215, 215);}");
}

//鼠标离开哪个QWidget时，将颜色恢复
void SessionFriendItem::leaveEvent(QEvent* event)
{
    (void)event;
    if (this->selected) {
        return;
    }
    // 还原背景色
    this->setStyleSheet("QWidget { background-color: rgb(231, 231, 231);}");
}

// 会话 Item 的实现
SessionItem::SessionItem(QWidget* owner,const QString& chatSessionId,const QIcon& avatar,const QString& name,const QString& lastMessage)
    :SessionFriendItem(owner,avatar,name,lastMessage),chatSessionId(chatSessionId),text(lastMessage)
{
    // 处理最后一个消息的信号
    DataCenter* dataCenter = DataCenter::getInstance();
    connect(dataCenter, &DataCenter::updateLastMessage, this, &SessionItem::updateLastMessage);

    // 需要显示出未读消息的数目, 为了支持客户端重启之后, 未读消息仍然能正确显示.
    int unread = dataCenter->getUnread(chatSessionId);
    if (unread > 0) {
        // 存在未读消息
        this->messageLabel->setText(QString("[未读%1条] ").arg(unread) + text);
    }
}

// 好友 Item 的实现
FriendItem::FriendItem(QWidget* owner,const QString& userId,const QIcon& avatar,const QString& name,const QString& description)
:SessionFriendItem(owner,avatar,name,description),userId(userId)
{

}

// 好友申请 Item 的实现
ApplyItem::ApplyItem(QWidget* owner,const QString& userId,const QIcon& avatar,const QString& name)
    :SessionFriendItem(owner,avatar,name,""),userId(userId)
{
    // 消除messageLabel
    QGridLayout* layout = dynamic_cast<QGridLayout*>(this->layout());
    layout->removeWidget(messageLabel);
    //防止内存泄露
    delete messageLabel;

    //创建出同意和拒绝按钮
    QPushButton* acceptBtn = new QPushButton();
    acceptBtn->setText("同意");
    QPushButton* rejectBtn = new QPushButton();
    rejectBtn->setText("拒绝");
    acceptBtn->setStyleSheet("border: none;");
    rejectBtn->setStyleSheet("border: none;");

    layout->addWidget(acceptBtn,1,2,1,1);
    layout->addWidget(rejectBtn,1,3,1,1);

    connect(acceptBtn,&QPushButton::clicked,this, &ApplyItem::acceptFriendApply);
    connect(rejectBtn,&QPushButton::clicked,this, &ApplyItem::rejectFriendApply);
}

void SessionFriendArea::clickItem(int index)
{
    if(index < 0 || index > container->layout()->count()){
        LOG() << "点击元素的下标超出范围！ index=  " << index;
        return;
    }

    QLayoutItem* layoutItem = container->layout()->itemAt(index);
    //如果本身为空，或者里面的widget为空，就说明指定的元素不存在
    if(layoutItem == nullptr || layoutItem->widget() == nullptr) {
        LOG() << "指定的元素不存在! index= " << index;
        return;
    }

    SessionFriendItem* item = dynamic_cast<SessionFriendItem*>(layoutItem->widget());
    // 创建一个模拟的鼠标点击事件
    QPointF localPos(0, 0);
    QPointF screenPos = item->mapToGlobal(QPoint(0, 0));
    QMouseEvent* event = new QMouseEvent(QEvent::MouseButtonPress, localPos, screenPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);

    item->select(event);

    delete event;
}

void SessionFriendItem::active()
{
    //这里是让子类去重写此方法，不实现
}

 //点击之后，要在主界面右侧显示区中加载出对应的消息列表
void SessionItem::active()
{
    LOG() << "点击 SessionItem 触发的逻辑! chatSessionId=" << chatSessionId;

    MainWidget* mainWidget = MainWidget::getInstance();
    mainWidget->loadRecentMessage(chatSessionId);

    //清空未读数据,并加载出对应的消息
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    dataCenter->clearUnread(chatSessionId);

    this->messageLabel->setText(text);
}

void SessionItem::updateLastMessage(const QString &chatSessionId)
{
    DataCenter* dataCenter = DataCenter::getInstance();
    // 判断是不是同一个消息会话，如果不是，不需要更新最新的一条消息
    if (this->chatSessionId != chatSessionId) {
        return;
    }

    // 此时最新的一条消息就是自己发送的消息,获取到最新的一条消息
    QList<Message>* messageList = dataCenter->getRecentMessageList(chatSessionId);
    if (messageList == nullptr || messageList->size() == 0) {
        // 当前会话没有任何消息, 无需更新
        return;
    }
    Message lastMessage = messageList->back();

    // 判断是什么类型，然后将消息展示到会话展示区中
    if(lastMessage.messageType == TEXT_TYPE) {
        text = lastMessage.content;
    }else if(lastMessage.messageType == FILE_TYPE) {
        text = "[文件]";
    }else if(lastMessage.messageType == IMAGE_TYPE) {
         text = "[图片]";
    }else if(lastMessage.messageType == SPEECH_TYPE) {
        text = "[语音]";
    }else {
        LOG() << "错误的消息类型!";
        return;
    }
    // LOG() << chatSessionId << " " << dataCenter->getCurrentChatSessionId();
    if(chatSessionId == dataCenter->getCurrentChatSessionId()) {
        this->messageLabel->setText(text);
    }else {
        int unread = dataCenter->getUnread(chatSessionId);
        LOG() << "更新未读消息: " <<  unread;
        if(unread > 0) {
            this->messageLabel->setText(QString("[未读%1条] ").arg(unread) + text);
        }
    }
}

//点击之后，要切换会话列表，并且选中对应的回话
void FriendItem::active()
{
    LOG() << "点击 FriendItem 触发的逻辑! userId=" << userId;
    MainWidget* mainWidget = MainWidget::getInstance();
    mainWidget->switchSession(userId);
}

//点击之后，没有什么事 主要看接受 和 拒绝按钮 来操作
void ApplyItem::active()
{

}

void ApplyItem::acceptFriendApply()
{
    // 发送请求
    DataCenter* dataCenter = DataCenter::getInstance();

    // userId 是申请人的好友Id
    dataCenter->acceptFriendApplyAsync(this->userId);
}

void ApplyItem::rejectFriendApply()
{
    // 发送请求
    DataCenter* dataCenter = DataCenter::getInstance();

    // userId 是申请人的好友Id
    dataCenter->rejectFriendApplyAsync(this->userId);
}

